﻿// Copyright (C) 2009 - 2013 EvTech Project
//
// This program is free software: you can redistribute it and/or modify
// it under the +terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Piirto
{
    public class Sprite
    {
        Bitmap img;
        Bitmap rotatedImg;
        Rectangle bounds;
        int offsetX;
        int offsetY;
        float angle;
        Point oldLoc;
        public bool Visible;
        public bool Snapped;

        public Sprite(Image img)
        {
            this.img = (Bitmap)img;
            offsetX = 0;
            offsetY = 0;
            angle = 0;
            bounds = new Rectangle(0, 0, 20, 20);
            oldLoc = new Point(0, 0);
            Snapped = false;
            if (this.img == null)
            {
                this.img = new Bitmap(20, 20);
                Graphics g = Graphics.FromImage(img);
                g.FillEllipse(Brushes.Green, 0, 0, 20, 20);
                g.Dispose();
            }
            rotatedImg = RotateImage(this.img, 0);
        }

        public void Paint(Graphics g)
        {
            if (Visible)
            {
                g.DrawImage(rotatedImg, bounds.X, bounds.Y, bounds.Width, bounds.Height);
            }
        }

        internal void setSize(int p)
        {
            this.bounds.Width = p;
            this.bounds.Height = p;
            rotatedImg = RotateImage(img, 0);
        }

        internal void startDragging(int x, int y)
        {
            this.offsetX = x - bounds.X;
            this.offsetY = y - bounds.Y;
        }

        internal float getAngle()
        {
            return angle;
        }

        internal void setAngle(float angle)
        {
            this.angle = angle;
            rotatedImg = RotateImage(img, angle);
        }

        internal void drag(int x, int y)
        {
            if (Math.Abs(bounds.X - oldLoc.X) > bounds.Width || Math.Abs(bounds.Y - oldLoc.Y) > bounds.Width)
            {
                oldLoc = new Point(bounds.X, bounds.Y);
            }
            bounds.X = x - offsetX;
            bounds.Y = y - offsetY;

            if (oldLoc.X == bounds.X)
            {
                if (oldLoc.Y < bounds.Y)
                {
                    angle = 90;
                }
                else if (oldLoc.Y > bounds.Y)
                {
                    angle = 270;
                }
                // if old and current locations are same, do not change angle value 
            }
            else
            {
                //tan a = y/x
                angle = (float)((180d / Math.PI) * Math.Atan((((double)oldLoc.Y - bounds.Y) / ((double)oldLoc.X - bounds.X))));
                if (oldLoc.X > bounds.X)
                {
                    angle = 180 + angle;
                }
            }
            rotatedImg = RotateImage(img, angle);
        }

        internal bool testCollision(Bitmap background, Color colColor)
        {
            for (int y = 0; y < bounds.Height; y++)
            {
                for (int x = 0; x < bounds.Width; x++)
                {
                    if (x + bounds.X < 0 || y + bounds.Y < 0 || 
                        x + bounds.X >= background.Width || y + bounds.Y >= background.Height)
                    {
                        break;
                    }
                    if (background.GetPixel(x + bounds.X, y + bounds.Y).ToArgb() != colColor.ToArgb())
                    {
                        if (rotatedImg.Width <= x || rotatedImg.Height <= y)
                        {
                            break;
                        }
                        if (rotatedImg.GetPixel(x, y).A == 255)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        internal bool testCollision(int x, int y)
        {
            return bounds.Contains(x, y);
        }

        internal bool testCollision(Rectangle rec)
        {
            return bounds.IntersectsWith(rec);
        }

        internal Rectangle getBounds()
        {
            return bounds;
        }

        internal void setLocation(Point center)
        {
            bounds.X = center.X - (bounds.Width / 2);
            bounds.Y = center.Y - (bounds.Height / 2);
            oldLoc = new Point(bounds.X, bounds.Y);
        }

        internal Point getLocation()
        {
            return new Point(bounds.X + (bounds.Width / 2), bounds.Y + (bounds.Height / 2));
        }

        
        protected Bitmap RotateImage(Bitmap b, float angle)
        {
            Bitmap returnBitmap = new Bitmap(bounds.Width, bounds.Height);
            Graphics g = Graphics.FromImage(returnBitmap);
            g.Clear(Color.Transparent);
            int w, h;
            if (bounds.Width / (double)bounds.Height < b.Width / (double)b.Height)
            {
                w = bounds.Width;
                h = bounds.Width * b.Height / b.Width;
            }
            else
            {
                w = bounds.Height * b.Width / b.Height;
                h = bounds.Height;
            }
            g.TranslateTransform((float)returnBitmap.Width / 2, (float)returnBitmap.Height / 2);
            if (angle > 90 && angle < 270)
            {
                g.RotateTransform(180-angle);
            }
            else
            {
                g.RotateTransform(angle);
            }
            g.TranslateTransform(-(float)returnBitmap.Width / 2, -(float)returnBitmap.Height / 2);
            g.DrawImage(b, (bounds.Width - w) / 2, (bounds.Height - h) / 2, w, h);
            g.Dispose();
            if (angle > 90 && angle < 270)
            {
                returnBitmap.RotateFlip(RotateFlipType.RotateNoneFlipX);
            }
            return returnBitmap;
        }


        internal double getLength()
        {
            double scale = Math.Max(this.bounds.Width, this.bounds.Height) / (double)Math.Max(this.img.Width, this.img.Height);
            return Math.Sqrt(this.img.Width * this.img.Width + this.img.Height * this.img.Height) * scale;
        }

        public Image getImage()
        {
            return this.img;
        }

        internal void setImage(Image img)
        {
            if(img!=null)
                this.img = (Bitmap)img;
        }
    }
}
